/*
20 Avril 2016
Based on BASH_July15_v1_2
Renamed to v2.1 to be inline with the versions cde 'v' and 'V'

Fix the DB9 pinout issue (ANT1 GPO signal was on pin6 instead of pin3)
Only works with readers based on:
- SMART PRO module v2
- Enclosure side LED v4

-v 2.2
- change the order of the antenna
- delay 1s when starting the reading process

-v 2.3 7 Sept 2017
add watchdog reset
reverse the order the antenna

*/

//#include <SD.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <Wire.h>
//#include "RTClib.h"
#include "Arduino.h"
//#include <Tidratec_NFC_1_0.h>
//#include <AT24C512C.h>
#include <EEPROM.h>
//#include <SoftwareSerial.h>
//#include "Adafruit_FRAM_I2C.h"

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

#define SETBITMASK(x,y) (x |= (y))
#define CLEARBITMASK(x,y) (x &= (~y))
#define FLIPBITMASK(x,y) (x ^= (y))
#define CHECKBITMASK(x,y) (x & (y))

#define VARFROMCOMB(x, y) x
#define BITFROMCOMB(x, y) y

#define C_SETBIT(comb) SETBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CLEARBIT(comb) CLEARBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_FLIPBIT(comb) FLIPBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CHECKBIT(comb) CHECKBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))

#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}

#define CS_MAX3107 PORTB, 2
#define CS_FRAM PORTD, 3
//#define ANT_SWITCH PORTC, 0
//#define ANT_SWITCH PORTC, 3
#define ALARM_LIGHT PORTC, 1
#define TestPoint PORTD, 7

//BASH Project Smart Pro module v1.2 + side LED v4
#define ANT_SWITCH_V2 PORTC, 1
#define ANT_SWITCH_V3 PORTC, 2
#define ANT_SWITCH_V4 PORTC, 3
#define ANT_SWITCH_V1 PORTC, 0

//MAX3107
#define IRQEn 0x01
#define MAX3107_ISR 0x02
#define MODE1 0x09
#define MODE2 0x0A
#define LCR 0x0B
#define FIFOTrgLvl 0x10
#define RxFIFOLvl 0x12
#define BRGConfig 0x1B
#define DIVLSB 0x1C
#define CLKSource 0x1E
#define RevID 0x1F

#define EPC_Length_Max 18

#define BEGIN_state 1
#define EPC_state 2
#define ACK_PACKET_state 3
#define Flush_state 4

#define Antenna_status_OpAnt 0
#define Antenna_status_4Ant 1
#define OFF_status 0
#define ON_status 1
#define Operator_tag_type 1
#define Cylinder_tag_type 2
#define EPC_Length 6
#define MAX_Nb_Unique_Tag_INTERNAL 33
#define A (EPC_Length)
#define B (EPC_Length + 1)
#define C (EPC_Length + 2)

uint8_t COMMAND_TO_MODULE[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//uint8_t Data_from_module_EPC[EPC_Length_Max];
uint8_t Data_from_module_EPC[8];
//uint8_t Unique_Tag_ID[EPC_Length];
//uint8_t Operator_ID[EPC_Length];
uint8_t Data_from_module_SOF[3];
uint8_t Stand_alone_mode = 1;//0 = Stand alone mode OFF
uint8_t Counter_tag_read_confirmation;
uint8_t Counter_tag_no_read_confirmation;
uint8_t Antenna_status = 0;
uint8_t Operation_status = 0;
volatile uint8_t state = 0;
volatile uint8_t EOF_flag;
volatile uint8_t error_flag = 0;
volatile uint8_t length_trame;
volatile uint8_t tag_type = 0;
volatile uint8_t config_gas_type = 3;
volatile uint8_t theres_a_tag = 0;
volatile uint8_t tp_debug = 0;
uint8_t success;
uint8_t button_not_pressed;
//char serial_buffer[15];
uint8_t testt[2];//debug
uint8_t antenna_module_config;

uint8_t Nb_unique_EPC = 0;//per session, per antenna (SRAM)
//uint8_t Unique_EPC_table[MAX_Nb_Unique_Tag_INTERNAL][EPC_Length + 3];//[Ligne][colonne] = EPC + A + B + C
//A = current round counter
//B = tag seen counter
//C = tag not seen counter

uint8_t Counter_no_tag_present_config;
uint8_t Counter_no_tag_present[] = {0, 0, 0, 0};
uint8_t round_tag_counter[] = {0, 0, 0, 0};

void setup();
void loop();

//RTC_DS1307 rtc;
void WatchDog_set(void)
{
	SREG &= ~(1<<7);
	MCUSR &= ~(1<<3);
	WDTCSR =0x00;
	WDTCSR |= (1<<WDCE) | (1<<WDE);
	WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
	MCUSR |= 0x0F;
	SREG |= (1<< 7);
}
void SPI_MAX3107_read_FIFO(uint8_t * buffer, uint8_t nb_of_bytes)
{
	C_CLEARBIT(CS_MAX3107);
	
	SPDR = 0;
	while(!(SPSR & _BV(SPIF)));
	
	for (uint8_t i = 0; i < nb_of_bytes; i++)//
	{
		SPDR = 0;
		while(!(SPSR & _BV(SPIF)));
		
		buffer[i] = SPDR;
	}
	
	C_SETBIT(CS_MAX3107);
}

void SPI_MAX3107_send_command(const uint8_t * cde)
{
	C_CLEARBIT(CS_MAX3107);
	
	SPDR = 0x80;
	while(!(SPSR & _BV(SPIF)));
	
	for (uint8_t i = 0; i < 8; i++)//Write cde to FIFO buffer
	{
		SPDR = cde[i];
		while(!(SPSR & _BV(SPIF)));
	}
	
	C_SETBIT(CS_MAX3107);
	
	_delay_us(700);//check if really necessary (a priori non)
}

void SPI_MAX3107_write(uint8_t SPI_address, uint8_t SPI_data)
{
	C_CLEARBIT(CS_MAX3107);
	
	SPDR = SPI_address | 0x80;
	while(!(SPSR & _BV(SPIF)));
	
	SPDR = SPI_data;
	while(!(SPSR & _BV(SPIF)));
	
	C_SETBIT(CS_MAX3107);
}

uint8_t SPI_MAX3107_read(uint8_t SPI_address)
{
	C_CLEARBIT(CS_MAX3107);
	
	SPDR = SPI_address & 0x7f;
	while(!(SPSR & _BV(SPIF)));
	
	SPDR = 0;
	while(!(SPSR & _BV(SPIF)));
	
	C_SETBIT(CS_MAX3107);
	
	return SPDR;
}

void Flush_UART_Rx_Buffer(void)
{
	SPI_MAX3107_write(MODE2, 0x02);
	SPI_MAX3107_write(MODE2, 0x00);
}

void Flush_FIFO_manually(uint8_t nb_of_bytes)
{
	C_CLEARBIT(CS_MAX3107);
	
	SPDR = 0;
	while(!(SPSR & _BV(SPIF)));
	
	for (uint8_t i = 0; i < nb_of_bytes; i++)//
	{
		SPDR = 0;
		while(!(SPSR & _BV(SPIF)));
	}
	
	C_SETBIT(CS_MAX3107);
}

void Module_Initialization_2(void)//Initialisation pour lecture continue (production) BASH
{
	//Read some config fields from EEPROM
	//Counter_tag_read_confirmation = EEPROM.read(18); Counter_no_tag_present_config
	Counter_no_tag_present_config = EEPROM.read(18);
	
	//SPI_MAX3107_write(FIFOTrgLvl, 0x10);//Config IRQ when there are 8 bytes in Rx FIFO
	Serial.println("2.1");
	//CANCEL_CDE {0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[0] = 0x40;
	COMMAND_TO_MODULE[1] = 0x03;
	COMMAND_TO_MODULE[2] = 0x00;
	COMMAND_TO_MODULE[3] = 0x00;
	COMMAND_TO_MODULE[4] = 0x00;
	COMMAND_TO_MODULE[5] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(3);
	
	//SPI_MAX3107_read(ISR);//Clear MAX3107 INT
	
	for (uint8_t i = 0; i < 4; i++)//Logical antenna 4 (fifth antenna) is operator antenna
	{
		
		//Select logical antenna {0x01, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00}
		COMMAND_TO_MODULE[0] = 0x01;
		COMMAND_TO_MODULE[1] = 0x00;
		COMMAND_TO_MODULE[2] = 0x01;
		COMMAND_TO_MODULE[3] = 0x07;
		COMMAND_TO_MODULE[4] = i;
		COMMAND_TO_MODULE[5] = 0x00;
		SPI_MAX3107_send_command(COMMAND_TO_MODULE);
		_delay_ms(1);
		
		//Check if antenna should be enabled or disabled
		antenna_module_config = (EEPROM.read(10) >> i) & 0x01;
		//Serial.println("2.2 antenna_module_config: ");
		Serial.println(antenna_module_config, DEC);
		if(antenna_module_config)
		{
			//Serial.println("Enable logical antenna");
			//Enable logical antenna {0x01, 0x00, 0x02, 0x07, 0x01, 0x00, 0x00, 0x00}
			COMMAND_TO_MODULE[2] = 0x02;
			COMMAND_TO_MODULE[3] = 0x07;
			COMMAND_TO_MODULE[4] = 0x01;
			COMMAND_TO_MODULE[5] = 0x00;
			SPI_MAX3107_send_command(COMMAND_TO_MODULE);
			
			//Assign Physical Antenna {0x01, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00}
			COMMAND_TO_MODULE[2] = 0x04;
			COMMAND_TO_MODULE[3] = 0x07;
			COMMAND_TO_MODULE[4] = i;
			COMMAND_TO_MODULE[5] = 0x00;
			SPI_MAX3107_send_command(COMMAND_TO_MODULE);
			_delay_ms(1);
			
			//Set Dwell time {0x01, 0x00, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00} !!!Max dwell time limited to 0xFF 0xFF = 65 535 ms
			COMMAND_TO_MODULE[2] = 0x05;
			COMMAND_TO_MODULE[3] = 0x07;
			COMMAND_TO_MODULE[4] = EEPROM.read(14);//Dwell Low Byte
			COMMAND_TO_MODULE[5] = EEPROM.read(13);//Dwell High Byte
			SPI_MAX3107_send_command(COMMAND_TO_MODULE);
			_delay_ms(1);
			
			//Set Output Power {0x01, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00}
			COMMAND_TO_MODULE[2] = 0x06;
			COMMAND_TO_MODULE[3] = 0x07;
			COMMAND_TO_MODULE[4] = EEPROM.read(20 + 2*i);//Pout Low Byte		
			COMMAND_TO_MODULE[5] = EEPROM.read(19 + 2*i);//Pout High Byte
			SPI_MAX3107_send_command(COMMAND_TO_MODULE);
			_delay_ms(1);
		}
		else
		{
			//Serial.println("Disable logical antenna");
			//Disable logical antenna {0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00}//by default, all logical ant. disabled
			COMMAND_TO_MODULE[2] = 0x02;
			COMMAND_TO_MODULE[3] = 0x07;
			COMMAND_TO_MODULE[4] = 0x00;
			COMMAND_TO_MODULE[5] = 0x00;
			SPI_MAX3107_send_command(COMMAND_TO_MODULE);
			_delay_ms(1);
		}
	}
	//Serial.println("SET_INVMODE_SINGLE_CDE");
	//SET_INVMODE_SINGLE_CDE {0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x00;
	COMMAND_TO_MODULE[3] = 0x07;
	COMMAND_TO_MODULE[4] = 0x00;
	COMMAND_TO_MODULE[5] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);
	//Serial.println("2.3 SET_START_Q_0_CDE");
	//SET_START_Q_0_CDE {0x01, 0x00, 0x03, 0x09, 0xF0, 0x40, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x03;
	COMMAND_TO_MODULE[3] = 0x09;
	COMMAND_TO_MODULE[4] = 0xF0;
	COMMAND_TO_MODULE[5] = 0x40;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);

	/*//Tag Focus HST_IMPINJ_EXTENSIONS_CDE {0x01, 0x00, 0x03, 0x02, 0x10, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x03;
	COMMAND_TO_MODULE[3] = 0x02;
	COMMAND_TO_MODULE[4] = 0x10;
	COMMAND_TO_MODULE[5] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);

	//HST_QUERY_CFG_CDE {0x01, 0x00, 0x00, 0x09, 0xA0, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x00;
	COMMAND_TO_MODULE[3] = 0x09;
	COMMAND_TO_MODULE[4] = 0xA0;
	COMMAND_TO_MODULE[5] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);
	
	//HST_INV_ALG_PARM_2_CDE {0x01, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x05;
	COMMAND_TO_MODULE[3] = 0x09;
	COMMAND_TO_MODULE[4] = 0x00;
	COMMAND_TO_MODULE[5] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);*/
	//Serial.println("2.4 SET_FREQUENCY_CDE");
	//SET_FREQUENCY_CDE[] = {0x01, 0x00, 0x0A, 0x01, 0x38, 0xF6, 0x0D, 0x00};//default is 915 000 kHz (0D f6 38), Frequency reso = 125 kHz, 860 000 kHz = 0D 1F, 960 000 kHz = 0E A6 00
	COMMAND_TO_MODULE[2] = 0x0A;
	COMMAND_TO_MODULE[3] = 0x01;
	COMMAND_TO_MODULE[4] = EEPROM.read(17);
	COMMAND_TO_MODULE[5] = EEPROM.read(16);
	COMMAND_TO_MODULE[6] = EEPROM.read(15);
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);
	//Debug_cde(COMMAND_TO_MODULE);//Debug
	//Serial.println("2.5 SET_FREQUENCY_CFG_CDE");
	//SET_FREQUENCY_CFG_CDE[] = {0x01, 0x00, 0x08, 0x01, 0x01, 0x01, 0x00, 0x00}
	COMMAND_TO_MODULE[2] = 0x08;
	COMMAND_TO_MODULE[3] = 0x01;
	COMMAND_TO_MODULE[4] = 0x01;
	COMMAND_TO_MODULE[5] = 0x01;
	COMMAND_TO_MODULE[6] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(1);
	//Debug_cde(COMMAND_TO_MODULE);//Debug
	//Serial.println("2.6 WRITE_SET_FREQUENCY_CFG_CDE");
	//WRITE_SET_FREQUENCY_CFG_CDE[] = {0x01, 0x00, 0x00, 0xF0, 0x27, 0x00, 0x00, 0x00}//Attention, 32 bytes are sent bqck from the module
	COMMAND_TO_MODULE[2] = 0x00;
	COMMAND_TO_MODULE[3] = 0xF0;
	COMMAND_TO_MODULE[4] = 0x27;
	COMMAND_TO_MODULE[5] = 0x00;
	COMMAND_TO_MODULE[6] = 0x00;
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
	_delay_ms(30);
	//Debug_cde(COMMAND_TO_MODULE);//Debug
	
	Flush_UART_Rx_Buffer();
}

static void Project_pin_configuration(void)
{
	//0: input or NA
	//1: output
	
	//#define ANT_SWITCH_V2 PORTC, 2
	//#define ANT_SWITCH_V3 PORTC, 1
	//#define ANT_SWITCH_V4 PORTC, 3
	//#define ANT_SWITCH_V1 PORTC, 0
	
	//PC0 (23) = GPIOB1 -> DB9 pin 3 -> LED ANT1
	//PC1 (24) = GPIOB2 -> DB9 pin 4 -> LED ANT2
	//PC2 (25) = GPIOB3 -> DB9 pin 5 -> LED ANT3
	//PC3 (26) = GPIOB4 -> DB9 pin 6 -> LED ANT4
	
	//R2000 SMART PRO Module rev2.0
//********************************PORTB***********************************************
	//12. PB0 8 (PCINT0/CLKO/ICP1)	-> CLOCK OUT (fuse)				->NA
	//13. PB1 9 (PCINT1/OC1A)		-> GPIOB6						->Out
	//14. PB2 10 (PCINT2/SS/OC1B)	-> CS MAX3107 (high=disable)	->Out
	//15. PB3 11 (PCINT3/OC2A/MOSI)	-> SPI_MOSI						->Out
	//16. PB4 12 (PCINT4/MISO)		-> SPI_MISO	DTC					->NA
	//17. PB5 13 (SCK/PCINT5)		-> SPI_SCK DTC					->Out
	// 7. PB6 (PCINT6/XTAL1/TOSC1)	-> XTAL							->NA
	// 8. PB7 (PCINT7/XTAL2/TOSC2)	-> XTAL							->NA
	
	DDRB |= 0b00101110;
	//Disable MAX3107 (CS to high)
	C_SETBIT(CS_MAX3107);
	
	
//********************************PORTC***********************************************	
	//23. PC0 A0 (ADC0/PCINT8)		-> GPIOB1: Ant switch	->Out
	//24. PC1 A1 (ADC1/PCINT9)		-> GPIOB2: Light 		->Out
	//25. PC2 A2 (ADC2/PCINT10)		-> GPIOB3: test point	->Out
	//26. PC3 A3 (ADC3/PCINT11)		-> GPIOB4				->Out
	//27. PC4 A4 (ADC4/SDA/PCINT12)	-> I2C_SDA				->NA
	//28. PC5 A5 (ADC5/SCL/PCINT13)	-> I2C_SCL				->NA
	//29. PC6 (RESET/PCINT14)		-> RESET				->NA
	
	DDRC |= 0b00001111;
	
//********************************PORTD***********************************************
	 //30. PD0 0 (RXD/PCINT16)		-> Tx_Host			->NA (pin 1 FT232)
	 //31. PD1 1 (TXD/PCINT17)		-> Rx_Host			->NA
	 //32. PD2 2 (INT0/PCINT18)		-> IRQ MAX3107		->In
	 // 1. PD3 3 (PCINT19/OC2B/INT1)-> CE FRAM			->Out
	 // 2. PD4 4 (PCINT20/XCK/T0)	-> ANT4 Output	 	->Out
	 // 9. PD5 5 (PCINT21/OC0B/T1)	-> ANT0				->Out
	 //10. PD6 6 (PCINT22/OC0A/AIN0)-> A Ref			->In
	 //11. PD7 7 (PCINT23/AIN1)		-> ANT1/GPIOB7		->Out3 TEST POINT
	
	DDRD |= 0b10111000;
	//Disable FRAM (CS to high)
	C_SETBIT(CS_FRAM);
	
//	C_CLEARBIT(TestPoint);
	C_SETBIT(TestPoint);
	
	//Configure pull-up on Button input
	//pinMode(4, INPUT_PULLUP);
	
	//SPI Initialization
	//Mode 0 - MSB first - Master - 8MHz
	SPCR = 0b01010000;
	SPSR |= 0x01;
	//SPCR |= 0b01000000;
	
	//External Antenna Switch
	//All control pins to Vcc except V2 switched by the application
	//V2 is connected to PC0 = ANT_SWITCH
	//When v2 = LOW TRX3 is enabled (Antenna 5) -> Main Antenna
	//When v2 = HIGH TRX4 is enabled (Antenna 6) -> Operator Antenna
	//WARNING: On USB interface debug board, V2 is connected to PC3
}

void Send_INV_CDE(void)
{
	SPI_MAX3107_write(FIFOTrgLvl, 0x20);//config MAX3107 to INT after 16 next  bytes received
	
	//START_INV_CDE {0x01, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00}
	COMMAND_TO_MODULE[0] = 0x01;
	COMMAND_TO_MODULE[1] = 0x00;
	COMMAND_TO_MODULE[2] = 0x00;
	COMMAND_TO_MODULE[3] = 0xF0;
	COMMAND_TO_MODULE[4] = 0x0F;
	COMMAND_TO_MODULE[5] = 0x00;
	
	state = ACK_PACKET_state;
	Serial.println("Send_INV_CDE: to ACK");
	SPI_MAX3107_send_command(COMMAND_TO_MODULE);
}

void MAX3107_Interrupt_Management2(void)
{
	switch (state) 
	{
		case ACK_PACKET_state:
		{
		//	Serial.println("ACK");
			Flush_FIFO_manually(16);
			state = BEGIN_state;
	
			SPI_MAX3107_write(FIFOTrgLvl, 0x20);//config MAX3107 to INT after next 16 bytes received
		}
		break;
		
		case BEGIN_state:
		{
		//	Serial.println("BEGIN");
			Flush_FIFO_manually(2);
			
			SPI_MAX3107_read_FIFO(Data_from_module_SOF, 3);
			
			if(Data_from_module_SOF[0] == 1)//EOF alone
			{
			//	Serial.println("Data_from_module_SOF[0] == 1 -> EOF_flag =1");
				EOF_flag = 1;
				Flush_FIFO_manually(11);
				//SPI_MAX3107_read(ISR);//Clear MAX3107 INT
			}
			else if(Data_from_module_SOF[0] != 5)//verify this is a tag packet
			{
			//	Serial.println("Data_from_module_SOF[0] != 5 -> error_flag = 1");
				C_SETBIT(TestPoint);//debug
				error_flag = 1;
			}
			/*else if(Data_from_module_SOF[2] != 8)//verify the toal length frame is 40 bytes
			{
				error_flag = 2;
			}*/
			else
			{//EPC trame
				length_trame = Data_from_module_SOF[2]*4 - 16;//On ne calcul ici que ce qui reste a flusher apres la lecture des prochains 8 bytes
				
				Flush_FIFO_manually(11);
				
				state = EPC_state;
				
				SPI_MAX3107_write(FIFOTrgLvl, 0x10);//config MAX3107 to INT after next 8 bytes received
				//SPI_MAX3107_read(ISR);//Clear MAX3107 INT
			}
			
			//SPI_MAX3107_read(MAX3107_ISR);//Clear MAX3107 INT
		}
		break;
		
		case EPC_state://
		{
			
			SPI_MAX3107_read_FIFO(Data_from_module_EPC, 8);//Copy EPC + CRC inOctet = inOctet & 0xC0;
			
			switch ((Data_from_module_EPC[3] & 0xC0))
			{	
				case 0x00://Antenna 0
					if(round_tag_counter[3] != 255)
					{
						round_tag_counter[3]++;
					//	Serial.println("round_tag_counter[0]++");
					}
				break;
				
				case 0x40://Antenna 1
					if(round_tag_counter[0] != 255)
					{
						round_tag_counter[0]++;
					//	Serial.println("round_tag_counter[1]++");
					}
				break;
				
				case 0x80://Antenna 2
					if(round_tag_counter[2] != 255)
					{
						round_tag_counter[2]++;
					//	Serial.println("round_tag_counter[2]++");
					}
				break;
				
				case 0xC0://Antenna 3
					if(round_tag_counter[1] != 255)
					{
						round_tag_counter[1]++;
					//	Serial.println("round_tag_counter[3]++");
					}
				break;
			}
			
			//Flush the rest of the EPC data
			
			if(length_trame == 4)
			{
				while(SPI_MAX3107_read(RxFIFOLvl) != 4)
				{
				
				}
				Flush_FIFO_manually(4);
				
				state = BEGIN_state;
				
				SPI_MAX3107_write(FIFOTrgLvl, 0x20);//config MAX3107 to INT after next 16 bytes received
			}
			else if(length_trame == 8)
			{
				state = Flush_state;
				
				SPI_MAX3107_write(FIFOTrgLvl, 0x10);//config MAX3107 to INT after next 16 bytes received
			}
			
			else if( length_trame == 12)
			{
				state = Flush_state;
				
				SPI_MAX3107_write(FIFOTrgLvl, 0x10);//config MAX3107 to INT after next 8 bytes received
			}
			
			else if(length_trame == 16)
			{
				state = Flush_state;
				
				SPI_MAX3107_write(FIFOTrgLvl, 0x20);//config MAX3107 to INT after next 16 bytes received
			}
			else
			{
				error_flag = 3;
				
			}
		}
		break;
		
		case Flush_state://
		{
		
			Flush_FIFO_manually(8);
			
			if(length_trame == 12)
			{
				
				while(SPI_MAX3107_read(RxFIFOLvl) != 4)
				{
				    
				}
				Flush_FIFO_manually(4);
			}
			else if(length_trame == 16)
			{
				
				Flush_FIFO_manually(8);
			}
			else if(length_trame == 8)
			{
				
				//Do nothing
			}
			else
			{
				error_flag = 4;
				
			}
			
			state = BEGIN_state;
			
			SPI_MAX3107_write(FIFOTrgLvl, 0x20);//config MAX3107 to INT after next 16 bytes received
		}
		break;
	}
	
	SPI_MAX3107_read(MAX3107_ISR);//Clear MAX3107 INT
}

//////////////////
//
// 55 01 0203 01 1234 5678 01 222222222222


///////////////////////ERROR CODES///////////////////////
//
// 1 = trame is not a EOF or EPC packet
// 2 = EPC/trame is not right lenght
// 3 = tag is not Baosteel tag (no 0x55 at EPC start)
// 4 = not a operator nor cylinder tag
// 5 = this is a cylinder tag with wrong gas type
//
/////////////////////////////////////////////////////////

void Change_24V_Outputs(uint8_t Output_Port, uint8_t Output_State)
{
	switch (Output_Port) 
	{
		case 0:
			if (Output_State == 0)
			{
				C_CLEARBIT(ANT_SWITCH_V1);
			}
			else
			{
				C_SETBIT(ANT_SWITCH_V1);
			}
		break;
		
		case 1:
			if (Output_State == 0)
			{
				C_CLEARBIT(ANT_SWITCH_V2);
			}
			else
			{
				C_SETBIT(ANT_SWITCH_V2);
			}
		break;
		
		case 2:
			if (Output_State == 0)
			{
				C_CLEARBIT(ANT_SWITCH_V3);
			}
			else
			{
				C_SETBIT(ANT_SWITCH_V3);
			}
		break;
		
		case 3:
			if (Output_State == 0)
			{
				C_CLEARBIT(ANT_SWITCH_V4);
			}
			else
			{
				C_SETBIT(ANT_SWITCH_V4);
			}
		break;
	}
}

void setup()
{
	MCUSR = 0;
	wdt_disable();
	Project_pin_configuration();
	
	Serial.begin(19200); //Com with HOST
	
	//HW 2.0
	EEPROM.write(3, 48); //0
	EEPROM.write(4, 50); //2
	//S/N
	EEPROM.write(5, 49); //1
	EEPROM.write(6, 48); //0
	EEPROM.write(7, 48); //0
	EEPROM.write(8, 58); //2
	
	//rtc.begin();
	
	//MAX3107 Initialisation
	SPI_MAX3107_write(LCR, 0x03);//8b data, 1 stop, no parity
	SPI_MAX3107_write(BRGConfig, 0x0B);//FRACT = 11
	SPI_MAX3107_write(DIVLSB, 0x08);//D=8
	SPI_MAX3107_write(CLKSource, 0x18);//ext CLK
	SPI_MAX3107_write(IRQEn, 0x08);//Rx FIFO level on IRQ pin
	SPI_MAX3107_write(MAX3107_ISR, 0x08);//Enable Rx FIFO level int
	SPI_MAX3107_write(MODE1, 0x80);//Enable IRQ
	
	Flush_UART_Rx_Buffer();
	wdt_enable(WDTO_2S);
//	wdt_reset();
//	WatchDog_set();
	//attachInterrupt(0, MAX3107_Interrupt_Management, FALLING);
	
//////////////////EEPROM Mapping//////////////////////
//
// Add 0: 
// Add 1: 
// Add 2: 
// Add 3: HW_Version Low
// Add 4: HW_Version High
// Add 5: Board_SN Low
// Add 6: Board_SN
// Add 7: Board_SN
// Add 8: Board_SN High
// Add 9: Stand-alone flag (0: off - 1: on)
// Add 10: Nb_Antennas
// Add 11: Output Power High - OLD (version with same power value for all antennas)
// Add 12: Output Power Low - OLD (version with same power value for all antennas)
// Add 13: Dwell Time High
// Add 14: Dwell Time Low
// Add 15: Frequency High
// Add 16: Frequency Med
// Add 17: Frequency Low
// Add 18: Counter_tag_read_confirmation
// Add 19: Output Power High - Ant1
// Add 20: Output Power Low - Ant1
// Add 21: Output Power High - Ant2
// Add 22: Output Power Low - Ant2
// Add 23: Output Power High - Ant3
// Add 24: Output Power Low - Ant3
// Add 25: Output Power High - Ant4
// Add 26: Output Power Low - Ant4
// Add 27: Output Power High - Ant5
// Add 28: Output Power Low - Ant5
// Add 29: Counter_tag_no_read_confirmation
//
//////////////////////////////////////////////////////

}

void loop()
{
	if (Stand_alone_mode == 0)
	{	
		

		if (Serial.available() > 0)
		{
			int inByte = Serial.read();
			
			switch (inByte) 
			{
				case 's':
					Serial.print(F("s"));
					
					Stand_alone_mode = 1;
				break;
				
				case 'A'://Configure number of antennas individually (from 1 up to 4)
				{
					//0b00054321
					//1 = Antenna 1; 0 = disable; 1 = enable
					//2 = Antenna 2; 0 = disable; 1 = enable
					//3 = Antenna 3; 0 = disable; 1 = enable
					//4 = Antenna 4; 0 = disable; 1 = enable
					//5 = Antenna 5; 0 = disable; 1 = enable
					//ex: 0x0F for 4 antennas
					//ex: 0x04 for antenna 3 only
					//ex: 0x1F for 5 antennas
					
					while(Serial.available() < 1)//wait for the argument
					{
					
					}
					
					EEPROM.write(10, Serial.read()); //Save in EEPROM antenna_module_config
					
					//Send Ack
					Serial.print(F("A"));
				}
				break;
				
				case 'm'://
				{
					Serial.print(Stand_alone_mode);
				}
				break;
				
				case 'P'://Configure Output power
				{
					while(Serial.available() < 8)//wait for the arguments
					{
					
					}
					
					uint8_t Ant1_High = Serial.read();
					uint8_t Ant1_Low = Serial.read();
					uint8_t Ant2_High = Serial.read();
					uint8_t Ant2_Low = Serial.read();
					uint8_t Ant3_High = Serial.read();
					uint8_t Ant3_Low = Serial.read();
					uint8_t Ant4_High = Serial.read();
					uint8_t Ant4_Low = Serial.read();
					//uint8_t Ant5_High = Serial.read();
					//uint8_t Ant5_Low = Serial.read();
					
					if (Ant1_High != 0 || Ant1_Low != 0)
					{
						EEPROM.write(19, Ant1_High); //Save in EEPROM Output Power High - Ant1
						EEPROM.write(20, Ant1_Low); //Save in EEPROM Output Power Low - Ant1
					}
					
					if (Ant2_High != 0 || Ant2_Low != 0)
					{
						EEPROM.write(21, Ant2_High); //Save in EEPROM Output Power High - Ant2
						EEPROM.write(22, Ant2_Low); //Save in EEPROM Output Power Low - Ant2
					}
					
					if (Ant3_High != 0 || Ant3_Low != 0)
					{
						EEPROM.write(23, Ant3_High); //Save in EEPROM Output Power High - Ant3
						EEPROM.write(24, Ant3_Low); //Save in EEPROM Output Power Low - Ant3
					}
					
					if (Ant4_High != 0 || Ant4_Low != 0)
					{
						EEPROM.write(25, Ant4_High); //Save in EEPROM Output Power High - Ant4
						EEPROM.write(26, Ant4_Low); //Save in EEPROM Output Power Low - Ant4
					}
					
					/*if (Ant5_High != 0 || Ant5_Low != 0)
					{
						EEPROM.write(27, Ant5_High); //Save in EEPROM Output Power High - Ant4
						EEPROM.write(28, Ant5_Low); //Save in EEPROM Output Power Low - Ant4
					}*/
					
					//Send Ack
					Serial.print(F("P"));
				}
				break;
				
				case 'T'://Configure dwell time/timeout
				{
					while(Serial.available() < 2)//wait for the arguments
					{
					
					}
					
					EEPROM.write(13, Serial.read()); //Save High Byte in EEPROM
					EEPROM.write(14, Serial.read()); //Save Low byte in EEPROM
					
					//Send Ack
					Serial.print(F("T"));
				}
				break;
				
				case 'F'://Set Frequency
				{
					while(Serial.available() < 3)//wait for the arguments
					{
					
					}
					
					EEPROM.write(15, Serial.read()); //High Byte
					EEPROM.write(16, Serial.read()); //Med Byte
					EEPROM.write(17, Serial.read()); //Low Byte
					
					//Send Ack
					Serial.print(F("F"));
				}
				break;
				
				case 'B':
					while(Serial.available() < 1)//wait for the arguments
					{
					
					}
					
					Counter_no_tag_present_config = Serial.read();
					
					EEPROM.write(18, Counter_no_tag_present_config); //Save in EEPROM
					
					//Send Ack
					Serial.print(F("B"));
				break;
				
				case 'd':
					Serial.println(F("Dump EEPROM"));
					
					for (uint8_t i = 10; i < 30; i++)
					{
						Serial.print(i);
						Serial.print(": ");
						if (EEPROM.read(i) <= 0xF)
							Serial.print("0");
						Serial.println(EEPROM.read(i), HEX);
					}
				break;
				
				case '1'://
					Change_24V_Outputs(0, 0);
				break;
				
				case '2'://
					Change_24V_Outputs(0, 1);
				break;
				
				case '3'://
					Change_24V_Outputs(1, 0);
				break;
				
				case '4'://
					Change_24V_Outputs(1, 1);
				break;
				
				case '5'://
					Change_24V_Outputs(2, 0);
				break;
				
				case '6'://
					Change_24V_Outputs(2, 1);
				break;
				
				case '7'://
					Change_24V_Outputs(3, 0);
				break;
				
				case '8'://
					Change_24V_Outputs(3, 1);
				break;
				
				case '9'://
					Flush_UART_Rx_Buffer();
				break;
				
				case '0'://
					Serial.print("Rx FIFO level: ");
					Serial.println(SPI_MAX3107_read(RxFIFOLvl));
				break;
				
				case 'r'://Reset MCU Board
					Reset_AVR();
				break;
				
				case 'v':
					Serial.print(F("FW: "));//FW = 2.1
					Serial.write(50);
					Serial.print('.');
					Serial.write(49);
					Serial.println(F(""));
					
					Serial.print(F("HW: "));
					Serial.write(EEPROM.read(4));
					Serial.print('.');
					Serial.write(EEPROM.read(3));
					Serial.println(F(""));
					
					Serial.print(F("S/N: "));
					Serial.write(EEPROM.read(5));
					Serial.write(EEPROM.read(6));
					Serial.write(EEPROM.read(7));
					Serial.write(EEPROM.read(8));
					Serial.println(F(""));
				break;
				
				case 'V'://v 2.2
					Serial.write(50);
					Serial.print('.');
					Serial.write(50);
					
					Serial.write(EEPROM.read(4));
					Serial.print('.');
					Serial.write(EEPROM.read(3));
					
					Serial.write(EEPROM.read(5));
					Serial.write(EEPROM.read(6));
					Serial.write(EEPROM.read(7));
					Serial.write(EEPROM.read(8));
					
					for (uint8_t i = 10; i < 27; i++)
					{
						if (EEPROM.read(i) <= 0xF)
							Serial.print("0");
						Serial.print(EEPROM.read(i),HEX);
					}
				break;
			}
		}
		wdt_reset();
	}
	else
	{
		Serial.flush();
		Serial.println("1 begin");
		Serial.println("delay 1s");
		_delay_ms(1000);
		C_CLEARBIT(TestPoint);//debug
		uint8_t tp_debug = 0;
		state = ACK_PACKET_state;
		theres_a_tag = 0;
		error_flag = 0;
		EOF_flag = 0;
	//	Serial.println("2 befor Init");
		Module_Initialization_2();
	//	Serial.println("3 after Init");
		//Reset Counter_no_tag_present
		for (uint8_t i = 0; i < 4; i++)
		{
			Counter_no_tag_present[i] = 0;
		}
		
		//Reset counter tag round
		for (uint8_t i = 0; i < 4; i++)
		{
			round_tag_counter[i] = 0;
		}
		
		Flush_UART_Rx_Buffer();
	//	Serial.println("4 befor attach");
		attachInterrupt(0, MAX3107_Interrupt_Management2, FALLING);
	//	Serial.println("5 after attach, befor Send_INV_CDE");
		//SPI_MAX3107_write(MODE1, 0x80);//Enable IRQ
		
		Send_INV_CDE();
	//	Serial.println("6 after Send_INV_CDE");
		while((Serial.available() == 0) && error_flag == 0)
		{
			Serial.println("Serial.available==0 && error_flag == 0)");
			if(EOF_flag)
			{
				Serial.print("EOF_flag = ");
				Serial.println(EOF_flag, DEC);
				//Outputs management
				
				for (uint8_t i = 0; i < 4; i++)
				{
					if(round_tag_counter[i] > 0)
					{
						//Mettre a 24V la sortie correspondante a l'antenne
						Change_24V_Outputs(i, 1);
						Serial.print("r_t_c ");
						Serial.print(i+1, DEC);
						Serial.print(" : ");
						Serial.println(round_tag_counter[i], DEC);
						//Reset corresponding Counter_no_tag_present[]
						Counter_no_tag_present[i] = 0;
					}
					else
					{
						Counter_no_tag_present[i]++;
						Serial.print("C_n_t_p : ");
						Serial.println(i+1, DEC);

						if(Counter_no_tag_present[i] == Counter_no_tag_present_config)
						{
							//Mettre a 0 la sortie correspondante a l'antenne
							Change_24V_Outputs(i, 0);
						}
					}
				}
				
				EOF_flag = 0;
				
				//Reset counter tag round
				for (uint8_t i = 0; i < 4; i++)
				{
					round_tag_counter[i] = 0;
				}
				
				Send_INV_CDE();
			}
			
			//Serial.println("wait for watch dog reset!");
			//	_delay_ms(3000);
				
                        wdt_reset();
			
			
		}//while((Serial.available() == 0) && error_flag == 0)
		
		if(error_flag)
		{
		//	Stand_alone_mode = 0;
			Serial.print(F("Error code: "));
			Serial.println(error_flag);
			Serial.println(F("Operation stopped"));
			
			error_flag = 0;
		}
		else
		{
			Serial.println("enter last else");
			while(EOF_flag == 0)
			{
				Serial.println("blocking in while(EOF_flag == 0)!!!!!!!!!");
                          //    Stand_alone_mode=0;
                                break;
			}
			
			detachInterrupt(0);
			SPI_MAX3107_write(FIFOTrgLvl, 0x00);//disable MAX3107 INT
			Flush_UART_Rx_Buffer();
			
			uint8_t inByte2 = Serial.read();
			
			if (inByte2 == 'S')
			{
				Stand_alone_mode = 0;
			//	wdt_reset();
			//	wdt_disable();
				Serial.print(F("S"));
			}
			
			if (inByte2 == 'm')
			{
				Serial.print(Stand_alone_mode);
			}

			if(inByte2 == 'l')
			{
				Serial.print("wait for 3s");
				delay(3000);
			}
		}
	}
}